package com.bilibili.juc.atomic;

import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

/**
 * @author zuife
 * @description 需求：
 * 多线程并发调用一个类的初始化方法，如果违背初始化过，将执行初始化工作
 * 要求只能被初始化一次，只有一个线程操作成功
 * @since 2024-05-04 21:14:55
 */
public class AtomicReferenceFieldUpdaterDemo {
    public static void main(String[] args) {
        MyVariable myVariable = new MyVariable();
        for (int i = 0; i < 5; i++){
            new Thread(() -> {
                myVariable.init(myVariable);
            }, String.valueOf(i)).start();
        }

    }
}

class MyVariable {
    public volatile Boolean isInit = Boolean.FALSE;

    /**
     * 创建一个针对 MyVariable 类的 AtomicReferenceFieldUpdater 实例，用于更新名为 "isInit" 的布尔类型字段。
     * AtomicReferenceFieldUpdater 提供了一种原子方式来更新对象中的 volatile 字段，这对于多线程环境下的字段更新操作是十分有用的。
     * @param MyVariable 被更新字段所属的类
     * @param Boolean 更新字段的数据类型
     * @param "isInit" 字段名
     * @return 返回一个配置好的 AtomicReferenceFieldUpdater 实例，可以用于原子化更新 "isInit" 字段
     */
    AtomicReferenceFieldUpdater<MyVariable, Boolean> updater = AtomicReferenceFieldUpdater.newUpdater(MyVariable.class, Boolean.class, "isInit");

    public void init(MyVariable myVariable) {
        if (updater.compareAndSet(myVariable, Boolean.FALSE, Boolean.TRUE)) {
            System.out.println(Thread.currentThread().getName()+"\t"+"初始化成功");
            //暂停几秒钟线程
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"\t"+"初始化结束");
        } else {
            System.out.println( Thread.currentThread().getName()+"\t"+"已经初始化过了");
        }
    }
}
